{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "cb6a5a34",
   "metadata": {},
   "source": [
    "# Python 安装及基本语法"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "1294ec00",
   "metadata": {},
   "source": [
    "Python 是一种上手简单、功能丰富的编程语言，是数据科学领域首选的可靠工具。通过 Python 你可以迅速解决问题，而不是把精力消耗在复杂的语法与编程细节上，这与本教程的核心思想“简洁”不谋而合。\n",
    "\n",
    "当全世界的数据科学家与研究人员享受 Python 带来的便利时，另一部分人正在致力于开发各种强大的 数据分析 / 机器学习 / 神经网络运行库，使得复杂的算法和模型不再成为技术门槛，越来越多的人都有机会进入数据科学领域进行学习与创新。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "044f5e42",
   "metadata": {},
   "source": [
    "## 1.1.1 Python 安装运行"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "bfa93e3f",
   "metadata": {},
   "source": [
    "### 1.1.1.1 下载安装"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "b10fb80e",
   "metadata": {},
   "source": [
    "- 对于 Windows / Mac 用户，首先在官网 https://www.python.org/downloads/ 下载对应操作系统的 Python3 安装包，然后双击运行安装。\n",
    "\n",
    "- 对于Linux用户，执行 `sudo apt-get update && sudo apt-get install python3` 命令进行安装。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c07246c9",
   "metadata": {},
   "source": [
    "在安装完成后，打开命令提示符(win + R键，输入cmd回车) / 终端(command + 空格，输入term回车)，执行 python3 -V 命令，若出现对应python版本号则安装成功。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "318310ac",
   "metadata": {},
   "source": [
    "<img style=\"float: center;\" src=\"src/fig11.png\" width=\"50%\"> "
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "896e8b3f",
   "metadata": {},
   "source": [
    "### 1.1.1.2 编辑器与解释器\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c9784dc1",
   "metadata": {},
   "source": [
    "一个 Python 程序要经过“编写”和“运行”两个阶段。\n",
    "\n",
    "- 在编写阶段，我们通过【编辑器】完成后缀为.py程序代码的编写。\n",
    "- 在运行阶段，我们通过【解释器】运行编写好的程序。\n",
    "\n",
    "编辑器可以是notepad++、emeditor、甚至 windows 中最常见的 txt 编辑器。但为了提高我们的编程效率，我们往往选择功能更全面的 PyCharm 或者 vscode 等专用集成代码编辑器（IDLE）。\n",
    "\n",
    "解释器就是我们在上步安装的 python 可执行文件，在 windows 中它是 python3.exe，在 Mac / Linux 中它是名为 python3 的可执行文件。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "ec26345b",
   "metadata": {},
   "source": [
    "### 1.1.1.3 第一个Python程序"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "2e400540",
   "metadata": {},
   "source": [
    "在成功安装后，我们将尝试编写第一个Python程序。\n",
    "\n",
    "首先我们选择 Python 自带的IDLE编辑器\n",
    "- Windows 在 开始 -> 程序 -> Python3. -> IDLE (Python GUI) 打开\n",
    "- Mac 在 启动 -> IDLE 打开，然后菜单栏 File -> New File\n",
    "\n",
    "然后输入 `print(\"hello world\")`，并保存到任意位置，我们的程序编写阶段就完成啦！"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "20c7abf3",
   "metadata": {},
   "source": [
    "<img style=\"float: center;\" src=\"./src/fig12.png\" width=\"50%\"> "
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "84e8484b",
   "metadata": {},
   "source": [
    "下一步我们尝试用解释器运行保存的.py程序。\n",
    "\n",
    "首先通过命令行输入 `cd ~/***` 进入到文件存储的位置（这里 \\*\\*\\* 是你文件储存位置的路径）\n",
    "\n",
    "然后命令行执行 `Python3 test.py` 命令，这时输出 hello world 字样则程序运行成功！"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "52a946a6",
   "metadata": {},
   "source": [
    "<img style=\"float: center;\" src=\"./src/fig13.png\" width=\"50%\"> "
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "04586d92",
   "metadata": {},
   "source": [
    "### 1.1.1.4 交互式环境"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "5c8033c5",
   "metadata": {},
   "source": [
    "相比于其他编程语言，Python的一个特色是交互式环境，为我们提供了可以同时编写运行的编程方式。\n",
    "\n",
    "首先我们下载一个名为 jupyter notebook 的编辑器，它可以支持交互式环境。\n",
    "\n",
    "在命令行执行命令 `pip install jupyter` 安装编辑器。\n",
    "\n",
    "然后执行命令 `jupyter notebook`。\n",
    "\n",
    "这时你发现你的浏览器自动打开了，并且出现了一个在线的精美简洁的编辑器，这就是notebook的主界面。\n",
    "\n",
    "我们点击右上角的 New 按钮，选择 Python3，然后输入 `print('hello world')`，之后按下上面的 Run 按钮，这时我们发现在代码的下面也出现了hello world。\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "fc307911",
   "metadata": {},
   "source": [
    "<img style=\"float: center;\" src=\"./src/fig14.png\" width=\"50%\"> "
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c999a656",
   "metadata": {},
   "source": [
    "编写代码之后即刻运行，运行之后还可以继续编辑，省去了不停打开编写保存运行的过程，这便是交互式编程的奇妙之处！而交互式编程带来的便捷不止如此，在数据科学中我们经常要处理较大的数据，整个程序的运行动辄十几分钟。通过交互式编程我们可以一行一行运行程序，同时通过下面的输出内容观察程序的中间运行结果，在出现错误时及时修改代码，从而节省重复运行程序的时间！\n",
    "\n",
    "下面的教程中，交互式编程将全程陪伴你的学习过程，相信随着时间你会更加感触到先进工具带来的效率提升！"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "f738e935",
   "metadata": {},
   "source": [
    "## 1.1.2 Python 常量与变量"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "49d754df",
   "metadata": {},
   "source": [
    "可能你现在会产生疑惑，代码中的 print 代表什么意义？括号又是什么作用？为什么 hello world 外面有个双引号？没关系，下面我们就来了解 Python 语法的奥秘。\n",
    "\n",
    "首先我们介绍常量与变量，他们相当于语言中的 “名词” 部分，功能是用来表示某些事物。 "
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "381ba610",
   "metadata": {},
   "source": [
    "### 1.1.2.1 常量"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "cf0191ed",
   "metadata": {},
   "source": [
    "常量是编程语言中固定的量，它的值不能改变。例如 2 就表示数字二，不能被修改表示其他值。Python 中的常量包括数字，字符串，逻辑值三种。\n",
    "\n",
    "- 数字：整数（例如2），浮点数（例如2.333 或 1e-9 = $1 * 10^{-9}$）\n",
    "- 字符串：用单/双/三引号括起来的内容，例如（\\'Hi\\' 或 \\\"Hi\\\" 或 \\'\\'\\'Hi\\'\\'\\'）\n",
    "- 逻辑值：True 代表真， False 代表假\n",
    "\n",
    "使用 `type( * )` 可以查看 \\* 的类型，例如 `type(2)` 返回 int 表示 2 为 整数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "685b9615",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "int"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "## 2 表示 整数(integer) 2\n",
    "type(2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "62aa4541",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "float"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "## 2.333 与 1e-9 表示对应浮点数(float)\n",
    "type(2.33)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "dfa9993d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "float"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(1e-9)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "1188b441",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "str"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "## 用单引号括起来的内容表示字符串(string)\n",
    "\n",
    "type('这是1个字符串')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "31d968df",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "bool"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "## True 代表逻辑值(Boolen)\n",
    "type(True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "8fb8a11f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "bool"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "type(False)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "35483a24",
   "metadata": {},
   "source": [
    "### 1.1.2.2 变量"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "fd4b3a41",
   "metadata": {},
   "source": [
    "与常量相反，变量可以存储不同的值以表示不同的内容，并且它的值可以被更改。变量通过赋值符号 `=` 创建，例如 `variable = 1`。\n",
    "\n",
    "注意变量存在命名规范。变量的第一个字符必须是字母或下划线，其余部分由下划线或数字组成，且区分大小写。例如 `a_123` 可以是一个变量，123_a 不可以是一个变量，`A_123` 与 `a_123` 表示两个不同变量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "ae73cca9",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "int"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "## 创建名为 variable 的变量存储一个 整数 值\n",
    "\n",
    "variable = 1\n",
    "type(variable)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "da126551",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "str"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "## 修改 variable 变量的值为一个字符串\n",
    "\n",
    "variable = 'Hi'\n",
    "type(variable)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "6d88ecf8",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "cannot assign to literal (2270411785.py, line 3)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;36m  Input \u001b[0;32mIn [9]\u001b[0;36m\u001b[0m\n\u001b[0;31m    2.33 = 2.55\u001b[0m\n\u001b[0m    ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m cannot assign to literal\n"
     ]
    }
   ],
   "source": [
    "## 常量的值无法修改 触发语法错误提示\n",
    "\n",
    "2.33 = 2.55"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "f43e2af4",
   "metadata": {},
   "outputs": [
    {
     "ename": "SyntaxError",
     "evalue": "invalid decimal literal (4228011246.py, line 3)",
     "output_type": "error",
     "traceback": [
      "\u001b[0;36m  Input \u001b[0;32mIn [10]\u001b[0;36m\u001b[0m\n\u001b[0;31m    123_a = 1\u001b[0m\n\u001b[0m       ^\u001b[0m\n\u001b[0;31mSyntaxError\u001b[0m\u001b[0;31m:\u001b[0m invalid decimal literal\n"
     ]
    }
   ],
   "source": [
    "## 变量的命名不满足规范 触发语法错误提示\n",
    "\n",
    "123_a = 1"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "e49db2cb",
   "metadata": {},
   "source": [
    "## 1.1.3 Python 运算符与函数"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c1d6e269",
   "metadata": {},
   "source": [
    "学习了常量与变量之后，我们可以在 Python 中表示一些数值或字符串，然而要想解决更复杂的问题，我们需要了解如何对这些常量与变量进行操作。\n",
    "\n",
    "运算符与函数相当于语言中的 “动词” 部分，用来表示某种操作。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "f19dc5ce",
   "metadata": {},
   "source": [
    "### 1.1.3.1 运算符"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "6b9e4f82",
   "metadata": {},
   "source": [
    "运算符有以下几种，表示运算操作/逻辑操作/位运算操作\n",
    "\n",
    "- 算数运算符：\n",
    "    - `+` 表示加法，`1 + 2` 的结果是 3\n",
    "    - `-` 表示减法，`1 - 2` 的结果是 -1\n",
    "    - `*` 表示乘法，`1 * 2` 的结果是 2\n",
    "    - `**` 表示乘方，`1 ** 2` 的结果是 1\n",
    "    - `/` 表示除法，`1 / 2` 的结果是 0.5      \n",
    "    - `//` 表示整除，`1 // 2` 的结果是 0    （相当于除法结果向下取整）\n",
    "    - `%` 表示取余，`1 % 2` 的结果是 1\n",
    "    \n",
    "    \n",
    "- 逻辑运算符\n",
    "    - `>` 表示大于，`1 > 2` 的结果是 False\n",
    "    - `>=` 表示大于等于， `1 >= 2` 的结果是 False\n",
    "    - `<=` 表示小于，`1 <= 2` 的结果是 True\n",
    "    - `<` 表示小于等于， `1 < 2` 的结果是 True\n",
    "    - `==` 表示等于， `1 == 2` 的结果是 False\n",
    "    - `!=` 表示不等于， `1 != 2` 的结果是 True\n",
    "    - `and` 表示逻辑\"与\"，`True and False` 的结果是 False\n",
    "    - `or` 表示逻辑\"或\"，`True or False` 的结果是 True\n",
    "    - `not` 表示逻辑\"非\"，`not True` 的结果是 False\n",
    "    \n",
    "    \n",
    "- 位运算符\n",
    "    - `>>` 表示右移操作\n",
    "    - `<<` 表示左移操作\n",
    "    - `&` 表示按位与\n",
    "    - `|` 表示按位或\n",
    "    - `^` 表示按位异或\n",
    "    - `~` 表示按位取反\n",
    "    \n",
    "其中最常用的是算数运算符与逻辑运算符，位运算符在 集合 操作中经常使用。\n",
    "\n",
    "附：逻辑运算参照表\n",
    "\n",
    "| X     | Y     | X and Y | X or Y | not X | not Y |\n",
    "| ----- | ----- | ------- | ------ | ----- | ----- |\n",
    "| True  | True  | True    | True   | False | False |\n",
    "| True  | False | False   | True   | False | True  |\n",
    "| False | False | False   | False  | True  | True  |\n",
    "| False | True  | False   | True   | True  | False |\n"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "4ca325e9",
   "metadata": {},
   "source": [
    "> 问题：给你任意五个整数和一个目标值target，找到这五个整数中和为target的那两个整数。\n",
    "\n",
    "例如：\n",
    "\n",
    "    输入：2,3,7,11,15, target = 13\n",
    "    输出：2,11\n",
    "    解释：第0个数和第3个数的和为13 （注：编程时我们习惯从第0个开始数）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "2821138d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "## 尝试求解，改变 a b 的值依次两两尝试，直到 a + b = target\n",
    "\n",
    "target = 13\n",
    "a = 2\n",
    "b = 3\n",
    "a + b == target"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "d735f2c4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = 2\n",
    "b = 7\n",
    "a + b == target"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "6d18a586",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = 2\n",
    "b = 11\n",
    "a + b == target"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "0e477e9a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 11)"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a,b"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "6398ea1d",
   "metadata": {},
   "source": [
    "### 1.1.3.2 函数"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "fd415b9c",
   "metadata": {},
   "source": [
    "在上述过程中，下列代码被重复多次书写，这时我们可以使用函数减少代码冗余。函数是一种可复用的部件，用于定义更加复杂的操作以减少代码冗余。\n",
    "\n",
    "    a = *\n",
    "    b = *\n",
    "    a + b == target\n",
    "    \n",
    "如果把运算符比作 “握” “抬手” “张嘴” “吞咽” 等基本动作，那么函数往往是 “吃饭” “喝水” 等一系列基本动作构成的复杂动作。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "fed1bec7",
   "metadata": {},
   "source": [
    "函数通过 `def` 关键字定义，函数的输入由函数名后括号内 参数 定义，函数的结果由 `return` 关键字定义。\n",
    "\n",
    "- 函数的 参数 由逗号分隔，在定义函数时的参数叫做形参，在使用函数时输入的参数叫做实参。\n",
    "- 函数的 返回值 是函数的返回结果，参数与返回值都是可选的。\n",
    "\n",
    "另外程序中还存在着预先定义好的函数，例如我们在前面使用的 `type` 函数。以及 1.1.1.3 节中使用的 `print` 函数，它的功能是在屏幕输出某个变量的内容。可能你早就心存疑惑，为什么上面不用 `print` 也能输出呢？原因就在于交互式环境 notebook 会自动输出最后一个变量的内容。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "58f76199",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "13"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "## 自动输出最后的 target\n",
    "\n",
    "variable\n",
    "target"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "2e70c894",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Hi'"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "## 自动输出最后的 variable\n",
    "\n",
    "target\n",
    "variable"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "e1e4e4b2",
   "metadata": {},
   "source": [
    "下面我们尝试定义一个函数减少之前代码的冗余。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "7c3f5f65",
   "metadata": {},
   "outputs": [],
   "source": [
    "## num1，num2 是输入的参数， return 后面的 a+b==target 是函数的结果\n",
    "\n",
    "## 这里num1，num2，target 是形参\n",
    "def check_sum(num1, num2, target):\n",
    "    ## 在 def xxx(): 下面缩进的是函数的内容\n",
    "    a = num1\n",
    "    b = num2\n",
    "    return a + b == target"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "b7caf8c4",
   "metadata": {},
   "source": [
    "Python的一大语法特点是缩进敏感，这里第 5，6，7 行距离开头有 1个TAB / 4个空格 的距离并不只是为了美观，而是为了说明第 5,6,7 行是函数的内容。相比下面 C++ 函数用花括号的表示方法，相信你可以在这个角度感受 Python 的简洁。 \n",
    "\n",
    "    int check_sum(int num1, int num2, int target)\n",
    "    {\n",
    "        int a = num1;\n",
    "        int b = num2;\n",
    "        return a + b == target;\n",
    "    }\n",
    "    \n",
    "下面我们尝试调用前面定义的 check_sum 函数完成之前的任务。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "5a5c2851",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "False\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "## 这里 2,3,13 是实参，函数返回结果 False\n",
    "\n",
    "print(check_sum(2, 3, 13))\n",
    "\n",
    "print(check_sum(2, 7, 13))\n",
    "\n",
    "print(check_sum(2, 11, 13))"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "7a0d0603",
   "metadata": {},
   "source": [
    "通过引入函数，上面的小例子变得更加简洁。然而我们发现无论测试哪两个数字的和与target一致，target的值是始终不变的。我们可以通过引入 局部变量 与 全局变量 简化函数。\n",
    "\n",
    "- 局部变量：只在函数内部生效的变量，在函数外部无法使用。\n",
    "- 全局变量：在整个代码中都生效的变量，在函数内/外部都可使用。\n",
    "\n",
    "在 `check_sum` 中定义的变量 `a`, `b`, `num1`, `num2`, `target` 都属于局部变量。\n",
    "\n",
    "在 1.1.3.1 节中我们定义的 `target` 变量属于全局变量。当我们希望在函数内部使用全局变量时，应当用 `global` 关键字予以标注。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "021a6351",
   "metadata": {},
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'num1' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)",
      "\u001b[1;32m/Users/chuanyu/Code/learn-python-the-smart-way/1. Python 安装及基本语法.ipynb Cell 54'\u001b[0m in \u001b[0;36m<cell line: 3>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      <a href='vscode-notebook-cell:/Users/chuanyu/Code/learn-python-the-smart-way/1.%20Python%20%E5%AE%89%E8%A3%85%E5%8F%8A%E5%9F%BA%E6%9C%AC%E8%AF%AD%E6%B3%95.ipynb#ch0000053?line=0'>1</a>\u001b[0m \u001b[39m## 尝试在函数外部使用变量 num1，系统报错 num1 未定义\u001b[39;00m\n\u001b[0;32m----> <a href='vscode-notebook-cell:/Users/chuanyu/Code/learn-python-the-smart-way/1.%20Python%20%E5%AE%89%E8%A3%85%E5%8F%8A%E5%9F%BA%E6%9C%AC%E8%AF%AD%E6%B3%95.ipynb#ch0000053?line=2'>3</a>\u001b[0m \u001b[39mprint\u001b[39m(num1)\n",
      "\u001b[0;31mNameError\u001b[0m: name 'num1' is not defined"
     ]
    }
   ],
   "source": [
    "## 尝试在函数外部使用变量 num1，系统报错 num1 未定义\n",
    "\n",
    "print(num1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "b9333b51",
   "metadata": {},
   "outputs": [],
   "source": [
    "## 尝试重新定义函数 check_sum, 此时函数参数中已不存在target\n",
    "\n",
    "def check_sum(num1, num2):\n",
    "    global target\n",
    "    a = num1\n",
    "    b = num2\n",
    "    return a + b == target"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "bdff7aaa",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "False\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "print(check_sum(2, 3))\n",
    "\n",
    "print(check_sum(2, 7))\n",
    "\n",
    "print(check_sum(2, 11))"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "a91f7105",
   "metadata": {},
   "source": [
    "通过 全局变量 的方法，我们的函数变得更加简洁了。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "79c45b74",
   "metadata": {},
   "source": [
    "## 1.1.4 Python 控制流"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "a60fdced",
   "metadata": {},
   "source": [
    "通过运算符与函数，我们可以操作变量完成简单的任务。然而本质上我们还在把 Python 当作一个计算器使用，而不是一个可以实现自动化的编程语言，每行代码按照自上而下的顺序依次执行。通过控制流，我们可以让程序自动判断逻辑，自动跳转到某个位置，从而实现自动控制。\n",
    "\n",
    "控制流中涉及几个关键字：\n",
    "\n",
    "- `if-else` 逻辑语句：判断某个条件是否成立，若成立则执行 if 语句，若不成立则执行 else 语句。\n",
    "- `while` 循环语句：根据某一条件重复执行某个语句块。\n",
    "- `for-in` 循环语句：根据某一序列进行循环迭代，直到迭代完整个序列。（序列这一概念在下章介绍）\n",
    "- `break` 停止语句：停止当前 while 或 for-in 循环。\n",
    "- `continue` 继续语句：暂停当前 while 或 for-in 循环，继续执行循环到下一个迭代。\n",
    "\n",
    "控制流就像语言中的“介词”，帮助我们联接名词与动词组成流畅优美的句子。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "217e80bb",
   "metadata": {},
   "source": [
    "### 1.1.4.1 while 循环语句\n",
    "\n",
    "while 循环语句根据某一条件重复执行某个语句块，它的基本结构如下：\n",
    "\n",
    "    while ***:\n",
    "        statement\n",
    "\n",
    "若 \\*\\*\\* 的结果为 True 则继续重复执行 statement，若结果为 False 则停止循环。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "cfe76091",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n"
     ]
    }
   ],
   "source": [
    "## while 循环语句样例\n",
    "\n",
    "a = 0\n",
    "while a < 5:\n",
    "    a = a + 1\n",
    "    print(a)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "2f69d818",
   "metadata": {},
   "source": [
    "在上面的代码中，首先我们定义变量 a 的值为 0，之后每次迭代使 a 的值增加 1，并输出当前 a 的值。\n",
    "\n",
    "当 a 的值等于 5 时，循环停止。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "14a678af",
   "metadata": {},
   "source": [
    "### 1.1.4.2 for 循环语句\n",
    "\n",
    "for-in 据某一序列进行循环迭代，直到迭代完整个序列。\n",
    "\n",
    "首先我们简单介绍下序列，序列只是一个有序的项的集合。例如方括号括起来的一组常量或变量 `[0, 1, 2, 3, 4]` 可以是一个序列。\n",
    "\n",
    "循环的基本结构如下：\n",
    "\n",
    "    for * in ***:\n",
    "        statement\n",
    "\n",
    "其中 \\*\\*\\* 是被迭代的序列，\\* 是存储当前迭代元素的变量，当 \\*\\*\\* 中所有元素都被迭代一次后，循环停止。\n",
    "\n",
    "在下面的代码中，每次循环迭代序列中的一个元素，直到最后一个元素 5 被迭代。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "744fb4f9",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n"
     ]
    }
   ],
   "source": [
    "## for-in 循环语句样例\n",
    "\n",
    "for i in [1,2,3,4,5]:\n",
    "    print(i)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "fa4b05e5",
   "metadata": {},
   "source": [
    "考虑之前的求和问题，在最坏的情况下，我们需要把所有元素两两求和才能得到答案。在5个元素时，我们最多需要对比10次，也就是重复写10次 check_sum 函数。但在有100个元素时，我们需要重复写4950次！因此这时我们用循环进行简化："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "0511b2de",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2 2 False\n",
      "2 3 False\n",
      "2 7 False\n",
      "2 11 True\n",
      "2 15 False\n",
      "3 2 False\n",
      "3 3 False\n",
      "3 7 False\n",
      "3 11 False\n",
      "3 15 False\n",
      "7 2 False\n",
      "7 3 False\n",
      "7 7 False\n",
      "7 11 False\n",
      "7 15 False\n",
      "11 2 True\n",
      "11 3 False\n",
      "11 7 False\n",
      "11 11 False\n",
      "11 15 False\n",
      "15 2 False\n",
      "15 3 False\n",
      "15 7 False\n",
      "15 11 False\n",
      "15 15 False\n"
     ]
    }
   ],
   "source": [
    "## 依次迭代元素 a，一共迭代 5 次\n",
    "for a in [2,3,7,11,15]:\n",
    "    ## 依次迭代元素 b，一共迭代 5 次\n",
    "    for b in [2,3,7,11,15]:\n",
    "        ## 每个元素 a 与 5 个元素 b 依次两两尝试，一共迭代了 5 * 5 = 25 次\n",
    "        print(a, b, check_sum(a, b))"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "e5ab42e9",
   "metadata": {},
   "source": [
    "在这个例子中，我们可以看到循环是可以嵌套的，在循环的每一次迭代中开启一个新的循环。外层的 `for a in [2, 3, 7, 11, 15]` 按照顺序选择第 1 个元素，内层的 `for b in [2, 3, 7, 11, 15]` 按照顺序选择第 2 个元素，每次迭代输出两个值以及是否与 target 相等。\n",
    "\n",
    "最终我们找到输出 True 的两个元素 ( 2, 11 )，只要三行代码就可以解决问题！"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "0e643a79",
   "metadata": {},
   "source": [
    "### 1.1.4.3 if-else 逻辑语句\n",
    "\n",
    "if else 逻辑语句根据某一条件运行不同代码，它的基本结构如下：\n",
    "\n",
    "    if ***:\n",
    "        statement1\n",
    "    else:\n",
    "        statement2\n",
    "\n",
    "若 \\*\\*\\* 的结果为 True 则执行 statement1，若结果为 False 则执行 statement2"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "5492c679",
   "metadata": {},
   "source": [
    "> 女朋友说，下班回来带一个西瓜。如果看到番茄，就买两个。最后程序员买回来两个西瓜。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "4d539bb4",
   "metadata": {},
   "source": [
    "虽然通过 for-in 不需要写很长代码，然而我们还需要从输出结果中一个个找。通过 if-else 逻辑语句，我们可以让程序真正的实现自动化！\n",
    "\n",
    "这里 pass 代表不进行任何操作。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "25812afe",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2 11\n",
      "11 2\n"
     ]
    }
   ],
   "source": [
    "## 加入 if-else 逻辑语句\n",
    "\n",
    "for a in [2,3,7,11,15]:\n",
    "    for b in [2,3,7,11,15]:\n",
    "        ## 如果 check_sum(a,b)的结果为 True 则 输出，否则什么也不做\n",
    "        if check_sum(a,b):\n",
    "            print(a, b)\n",
    "        else:\n",
    "            pass"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "72ef95bd",
   "metadata": {},
   "source": [
    "通过 if-else 逻辑语句，我们仅输出求和等于 target 的两个元素，不再需要从输出结果中逐个查找。"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "31e9a100",
   "metadata": {},
   "source": [
    "### 1.1.4.4 break 停止语句"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "d0f9c702",
   "metadata": {},
   "source": [
    "break 停止语句用于停止当前的循环。在上面的例子中，我们仅输出 1 种顺序即可，可以添加 break 停止语句在找到符合条件的两个元素后停止。\n",
    "\n",
    "注意 break 仅能跳出当前循环，因此我们需要添加一个 finded 变量记录是否已找到符合条件的两个元素，若找到后外层循环也使用 break 跳出。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "56a56ccc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2 11\n"
     ]
    }
   ],
   "source": [
    "## 添加 break 停止语句\n",
    "\n",
    "## finded 初始为 False\n",
    "finded = False\n",
    "for a in [2,3,7,11,15]:\n",
    "    for b in [2,3,7,11,15]:\n",
    "        if check_sum(a,b):\n",
    "            print(a, b)\n",
    "            ## 若找到则 finded 变为 True\n",
    "            finded = True\n",
    "            break\n",
    "        else:\n",
    "            pass\n",
    "    ## 若 finded 为 True，停止外层循环\n",
    "    if finded:\n",
    "        break"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "c732b477",
   "metadata": {},
   "source": [
    "### 1.1.4.5 continue 继续语句"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "a39a47d1",
   "metadata": {},
   "source": [
    "continue 语句用于停止当前循环并继续执行循环到下一个迭代，下面我们用一个例子展示 continue 的用法。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "6c93c544",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "3\n",
      "7\n",
      "11\n",
      "15\n"
     ]
    }
   ],
   "source": [
    "for a in [2,3,7,11,15]:\n",
    "    print(a)\n",
    "    continue\n",
    "    ## continue 使循环停止，并继续执行下一个迭代，后面的内容被跳过\n",
    "    print(a + 1)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "49f3381b",
   "metadata": {},
   "source": [
    "## 1.1.5 练习"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "7d40b4b2",
   "metadata": {},
   "source": [
    "### 1.1.5.1 练习一"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "dd204ed4",
   "metadata": {},
   "source": [
    "> 按规定，某种电子元件使用寿命超过 1000 小时为一级品。已知某一大批产品的一级品率为 0.2，现在从中随机地抽查 20 只。使用 Python 计算 20 只元件中恰好有 k 只 (k=0,1,...,20) 为一级品的概率为？"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "63a98fcd",
   "metadata": {},
   "source": [
    "根据二项分布公式，所求的概率为：\n",
    "\n",
    "$$P\\{X=k\\}=\\left(\\begin{array}{c}\n",
    "20 \\\\\n",
    "k\n",
    "\\end{array}\\right)(0.2)^{k}(0.8)^{20-k}, k=0,1, \\cdots, 20$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "ba81f4e4",
   "metadata": {},
   "outputs": [],
   "source": [
    "## 定义阶乘函数，用于排列组合中\n",
    "def multiple(x):\n",
    "    result = 1\n",
    "    while x != 0:\n",
    "        result = result * x\n",
    "        x = x - 1\n",
    "    return result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "d2e65330",
   "metadata": {},
   "outputs": [],
   "source": [
    "## 定义二项分布计算函数\n",
    "def p_xk(k):\n",
    "    ## 计算排列组合\n",
    "    temp = multiple(20) / (multiple(k) * multiple(20 - k))\n",
    "    ## 计算概率\n",
    "    p = (0.2 ** k) * (0.8 ** (20 - k))\n",
    "    return temp * p"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "66c451c4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "P{ X = 0 } =  0.011529215046068483\n",
      "P{ X = 1 } =  0.05764607523034242\n",
      "P{ X = 2 } =  0.13690942867206327\n",
      "P{ X = 3 } =  0.20536414300809488\n",
      "P{ X = 4 } =  0.21819940194610074\n",
      "P{ X = 5 } =  0.17455952155688062\n",
      "P{ X = 6 } =  0.10909970097305038\n",
      "P{ X = 7 } =  0.054549850486525185\n",
      "P{ X = 8 } =  0.022160876760150862\n",
      "P{ X = 9 } =  0.007386958920050286\n",
      "P{ X = 10 } =  0.0020314137030138287\n",
      "P{ X = 11 } =  0.00046168493250314287\n",
      "P{ X = 12 } =  8.65659248443393e-05\n",
      "P{ X = 13 } =  1.3317834591436813e-05\n",
      "P{ X = 14 } =  1.6647293239296018e-06\n",
      "P{ X = 15 } =  1.6647293239296019e-07\n",
      "P{ X = 16 } =  1.3005697843200012e-08\n",
      "P{ X = 17 } =  7.65041049600001e-10\n",
      "P{ X = 18 } =  3.1876710400000044e-11\n",
      "P{ X = 19 } =  8.38860800000001e-13\n",
      "P{ X = 20 } =  1.0485760000000012e-14\n"
     ]
    }
   ],
   "source": [
    "## 根据二项分布计算概率\n",
    "k = 0\n",
    "while k != 21:\n",
    "    print('P{ X =',k,'} = ', p_xk(k))\n",
    "    k = k + 1"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.9.7 ('base')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": false,
   "sideBar": true,
   "skip_h1_title": true,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": true
  },
  "vscode": {
   "interpreter": {
    "hash": "c6e4e9f98eb68ad3b7c296f83d20e6de614cb42e90992a65aa266555a3137d0d"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
